#include<stdio.h>
#include<malloc.h>

typedef struct photo_head{
	int type;
	int length;
	int x;
	int y;
	int ccount;
} head;

typedef struct photo_color{
	unsigned char red;
	unsigned char green;
	unsigned char blue;
	unsigned char alpha;
	int index;
	struct photo_color* next;
} color;

typedef struct photo_content{
	head head;
	color* colors;
	int* pixels; 
} photo;

photo* new(int x,int y){
    photo* new_photo = (photo*)malloc(sizeof(photo));
	int size = 0;
	new_photo->head.type = 8;
	new_photo->head.x = x;
	new_photo->head.y = y;
	new_photo->head.length = 0;
	new_photo->head.ccount = 0;
	new_photo->colors = NULL;
	size = x * y;
	new_photo->pixels = (int*)malloc(sizeof(int) * size);
	memset(new_photo->pixels,0,sizeof(int) * size);
	return new_photo;
}

int newColor(unsigned char r,unsigned char g ,unsigned char b,unsigned char a,photo* new_photo){
	color* tmp = new_photo->colors;
	if(tmp == NULL){
		new_photo->colors = (color*)malloc(sizeof(color));
		new_photo->colors->red = r;
		new_photo->colors->green = g;
		new_photo->colors->blue = b;
		new_photo->colors->alpha = a;
		new_photo->colors->index = 0;
		new_photo->colors->next = NULL;
		new_photo->head.ccount += 1;
		tmp = new_photo->colors;
	}
	while(1){
		if(tmp->next == NULL){
			tmp->next = (color*)malloc(sizeof(color));
			tmp->next->red = r;
			tmp->next->green = g;
			tmp->next->blue = b;
			tmp->next->alpha = a;
			tmp->next->index = tmp->index + 1;
			tmp->next->next = NULL;
			new_photo->head.ccount += 1;
			return tmp->next->index;
		}
		tmp = tmp->next;
	}
}

void point(int x,int y,int color,photo* new_photo){
	*(new_photo->pixels + new_photo->head.x * y + x) = color;
}

void setBg(int color,photo* new_photo){
	struct photo_color* tmp = new_photo->colors;
	while(color > 0){
		tmp = tmp->next;
		--color;
	}
	new_photo->colors->red = tmp->red;
	new_photo->colors->green = tmp->green;
	new_photo->colors->blue = tmp->blue;
	new_photo->colors->alpha = tmp->alpha;
}

void line(int x_start,int y_start,int x_end,int y_end,int color,photo* new_photo){
	int x_tmp = x_start <= x_end?x_start:x_end;
	int y_tmp = y_start <= y_end?y_start:y_end;
	int x_tmp_end = x_start <= x_end?x_end:x_start;
	int y_tmp_end = y_start <= y_end?y_end:y_start;
	int i = 0;
	int tmp = 0;
	float x = 0.0;
	if(x_tmp == x_tmp_end && y_tmp == y_tmp_end){
		point(x_tmp,y_tmp,color,new_photo);
		return;
	}
	if(x_tmp == x_tmp_end){
		for(i = y_tmp;i <= y_tmp_end;++i ){
			*(new_photo->pixels + new_photo->head.x * i + x_tmp) = color;
		}
		return ;
	}
	if(y_tmp == y_tmp_end){
		for(i = x_tmp;i <= x_tmp_end;++i ){
			*(new_photo->pixels + new_photo->head.x * y_tmp + i) = color;
		}
		return ;
	}
	x = (y_tmp_end - y_tmp)/(x_tmp_end - x_tmp);
	for(i = x_tmp;i <= x_tmp_end;++i ){
		tmp = (int)(x * (i - x_tmp) + y_tmp);
		*(new_photo->pixels + new_photo->head.x * tmp + i) = color;
	}
}

int saveToFile(unsigned char* filename,photo* new_photo){
	FILE* fp = NULL;
	int length = 0;
	int tmp = 0;
	color* tmp_color = new_photo->colors;
	if(tmp_color == NULL){
		return -1;
	}
	fp = fopen(filename,"wb");
	tmp = fwrite(&new_photo->head,sizeof(head),1,fp);
	length += tmp * sizeof(head);
	while(tmp_color != NULL){
		fwrite(&tmp_color->red,sizeof(unsigned char),1,fp);
		fwrite(&tmp_color->green,sizeof(unsigned char),1,fp);
		fwrite(&tmp_color->blue,sizeof(unsigned char),1,fp);
		fwrite(&tmp_color->alpha,sizeof(unsigned char),1,fp);
		length += 4 * sizeof(unsigned char);
		tmp_color = tmp_color->next;
	}
	tmp = fwrite(new_photo->pixels,sizeof(int),new_photo->head.x * new_photo->head.y,fp);
	length += tmp * sizeof(int);
	fseek(fp,sizeof(int),0);
	fwrite(&length,sizeof(int),1,fp);
	fclose(fp);
	return 0;
}

int main(int argc,char* argv[]){
	photo* my_photo = NULL;
	int white = 0,black = 0;
	if(argc == 1){
		exit(1);
	}
	my_photo = new(500,500);
	white = newColor(255,255,255,0,my_photo);
	black = newColor(0,0,0,0,my_photo);
	setBg(white,my_photo);
	line(0,0,100,100,black,my_photo);
	saveToFile(argv[1],my_photo);
	return 0;
}
